//
//  Unit.swift
//  MoYoung
//
//  Created by sylar on 16/11/21.
//  Copyright © 2016年 sylar. All rights reserved.
//

import Foundation
import HandyJSON

/// 单位类型
public enum UnitType: String, CaseIterable, HandyJSONEnum {
    /// 公制
    case metric = "metric"
    /// 英制
    case imperial = "imperial"
}

public extension UnitType {
    
    var localeName: String {
        
        switch self {
        case .metric:
            return "unit_unit_system_metric".language
            
        case .imperial:
            return "unit_unit_system_english".language
            
        }
        
    }
    
}

extension UnitType {
    
    /// 距离单位转换
    public var baseDistance: DistanceUnitType {
        
        switch self {
        case .metric:
            return .km
        case .imperial:
            return .miles
        }
        
    }
    
    // 配速单位转换
    public var basePace: PaceUnitType {
        
        switch self {
        case .metric:
            return .min_km
        case .imperial:
            return .min_mi
        }
        
    }
    
}

public enum DistanceUnitType: String,  HandyJSONEnum {
    
    /// 米
    case m = "m"
    /// 千米
    case km = "km"
    /// 码
    case yd = "yd"
    /// 英里
    case miles = "miles"
    
}

public extension DistanceUnitType {
    
    
    var name: String {
        
        switch self {
        case .m:
            return "unit_m".language
        case .km:
           return "unit_km".language
        case .yd:
            return "unit_yd".language
        case .miles:
            return "unit_miles".language
        }
    }
    
    var dayName: String {
        return self.name + "/\("unit_everyday".language)"
        
    }
    
}

public enum PaceUnitType: String, HandyJSONEnum {
    
    case min_km = "min/km"
    case min_mi = "min/Mi"
    
}

public extension PaceUnitType {
    
    var name: String {
        
        switch self {
        case .min_km:
            return "gps_training_goal_setting_pace_current_unit".language
        case .min_mi:
            return "gps_training_goal_setting_pace_current_mi_unit".language
        }
    }
}


//MARK: - 单位转换
public class Unit: NSObject {
    
    /// 单位更改之后发出的通知
    public static let kUnitChangedNotifaction = Notification.Name("kUnitChangedNotifaction")
    
    private static let unituserDefaultsKey = "unit"
    
    public static let sharedInstance = Unit()
    
    public var myType: UnitType = .metric {
        
        didSet {
            
            if myType == oldValue {
                return
            }
            
            UserDefaults.standard.set(myType.rawValue, forKey: Unit.unituserDefaultsKey)
            NotificationCenter.default.post(name: Unit.kUnitChangedNotifaction, object: nil)
            
        }
        
    }
    
    public override init() {
        super.init()
        
        guard let unit = UserDefaults.standard.string(forKey: Unit.unituserDefaultsKey), let unitType = UnitType(rawValue: unit) else {
            return
        }
        
        myType = unitType
        
    }
    
    public func distanceName(_ distance: Int)->String {
        if (self.myType == .metric) {
            return distance > 1000 ? "unit_km".language : "unit_m".language
        }
        else {
            let yard = Double(distance) * 1.09
            return yard > 1760 ? "unit_miles".language : "unit_yd".language
        }
    }
    
    

    //转换长度
    public func convertDistance(_ distance: Int)->String  {
        
        if distance == 0 {
            return "--"
        }
        
        if (self.myType == .metric) {
            if (distance < 1000) {
                return String(distance)
            } else {
                let km = Double(Double(distance)*10/1000)/10.0
                return String(format: "%.2f",km)
            }
        }
        else {
            return self.convertMiles(distance)
        }
    }
    //转换长度
    public func convertDistanceForGPS(_ distance: Double)->String  {
        log.error(distance)
        if (self.myType == .metric) {
            if (distance < 1000) {
                return String(format: "%.2f",distance)
            }
            else {
                let km = Double(Double(distance)*10/1000)/10.0
                return String(format: "%.2f",km)
            }
        }
        else {
            return self.convertMilesForGPS(distance)
        }
    }
    
    //转换单位
    public func convertIn(_ distance: Int)->Int {
        return Int(Double(distance) * 0.39)
    }
    public func convertCm(_ weight: Int)->Int {
        return Int(Double(weight) * 2.54)
    }
    
    public func convertMiles(_ distance: Int)->String {
        if distance == 0 {
            return "--"
        }
        let yard = Double(distance) * 1.09
        if (yard > 1760) {
            let miles = Double(Int(Double(yard)/1760 * 100)) / 100
            return String(format: "%.2f",miles)
        } else {
            return String(Int(yard))
        }
    }
    
    public func convertMilesForGPS(_ distance: Double)->String {
        if (distance > 1700) {
            let miles = Double(Double(distance)*100/16093)/10.0
            return String(format: "%.2f",miles)
        }
        else {
            let yd = Double(distance) * 1.09
            return String(format: "%.2f",yd)
        }
    }
    
    public func convertLb(_ weight: Int)->Int {
        return Int(Double(weight) * 2.20)
    }
    public func convertKg(_ weight: Int)->Int {
        return Int(Double(weight) * 0.45)
    }
    

   public func getDistanceNameGPS()->String {
        
        if (self.myType == .metric) {
            return "unit_km".language
        } else {
            return "unit_miles".language
        }
    }
    
    public func returnPaceUnit() -> String {
        if self.myType == .metric {
            return "gps_training_goal_setting_pace_current_unit".language
        } else {
            return "gps_training_goal_setting_pace_current_mi_unit".language
        }
    }
    
    public func returnKcalUnit() -> String {
        return "unit_calorie".language
    }
    
   
}

// MARK: - GPS距离转换
extension Unit {
    
    /// 根据距离自动转换对应单位距离
    /// - Parameter distance: 原始距离
    /// - Returns:
    public func automationGPSDistanceOf(_ distance: Double) ->(distance: Double, unitType: DistanceUnitType) {
        
        
        switch myType {
        case .metric:
            let distance = distance * 10/1000/10.0
            let unitType: DistanceUnitType = distance > 1000 ? .km : .m
            let d: Double = distance > 1000 ? distance/1000 : distance
            return (d, unitType)
            
        case .imperial:
            
            if distance > 1700 {
                let yard = distance*100/16093/10.0
                let unitType: DistanceUnitType = .miles
                
                return (yard, unitType)
            }
            
            let yd = distance * 1.09
            let unitType: DistanceUnitType = .yd
            
            return (yd, unitType)
        }
        
    }
    

    /// 转换长度
    /// - Parameters:
    ///   - distance: 原始距离（m）
    ///   - template: 单位模版
    /// - Returns: （转换后距离，单位）
    public func GPSDistanceOf(_ distance: Double,  unit template: (metric: DistanceUnitType, imperial: DistanceUnitType)? = nil) ->(distance: Double, unitType: DistanceUnitType) {
        
        switch myType {
        case .metric:
            
            var unitType: DistanceUnitType
            var d: Double
            
            if template?.metric == .km {
                
                d = distance * 10/1000/10.0
                unitType = .km
            } else if template?.metric == .m {
                d = distance
                unitType = .m
                
            } else {
                unitType = distance > 1000 ? .km : .m
                d = distance > 1000 ? distance * 10/1000/10.0 : distance
            }
            
            return (d, unitType)
            
        case .imperial:
            
            var unitType: DistanceUnitType
            var y: Double
            
            if template?.imperial == .miles {
                y = distance * 100/16093/10.0
                unitType = .miles
            } else if template?.imperial == .yd {
                y = distance * 1.09
                unitType = .yd
                
            } else {
                
                if distance > 1700 {
                    y = distance*100/16093/10.0
                    unitType = .miles
                    
                } else {
                
                    y = distance * 1.09
                    unitType = .yd
                }
  
            }
            
            return (y, unitType)
        }
        
    }
    
    
}

// MARK: - 距离转换
extension Unit {
    
    
    /// 目标距离公制转公/英制
    /// - Parameter distance: 公/英制距离
    /// - Returns: 公/英制
    public func goalDistance(_ distance: Double) ->(distance: Double, unitype: UnitType) {
        
        switch myType {
            
        case .metric:
            return (distance, self.myType)
        case .imperial:
            return (Double(Int(distance / 1.609)), self.myType)
        }
        
    }
    
    /// 根据距离自动转换对应单位距离
    /// - Parameter distance: 原始距离
    /// - Returns:
    public func automationDistanceOf(_ distance: Double) ->(distance: Double, unitType: DistanceUnitType) {
        switch myType {
        case .metric:
            
            let unitType: DistanceUnitType = distance > 1000 ? .km : .m
            let d: Double = distance > 1000 ? distance/1000 : distance
            return (d, unitType)
            
        case .imperial:
            
            let yard = distance * 1.09
            let unitType: DistanceUnitType = yard > 1760 ? .miles : .yd
            let y: Double = yard > 1760 ? yard/1760 : yard
            return (y, unitType)
        }
        
    }
    

    /// 转换长度
    /// - Parameters:
    ///   - distance: 原始距离（m）
    ///   - template: 单位模版
    /// - Returns: （转换后距离，单位）
    public func distanceOf(_ distance: Double, unit template: (metric: DistanceUnitType, imperial: DistanceUnitType)? = nil) ->(distance: Double, unitType: DistanceUnitType) {
        
        switch myType {
        case .metric:
            
            var unitType: DistanceUnitType
            var d: Double
            
            if template?.metric == .km {
                d = distance/1000
                unitType = .km
            } else if template?.metric == .m {
                d = distance
                unitType = .m
                
            } else {
                unitType = distance > 1000 ? .km : .m
                d = distance > 1000 ? distance/1000 : distance
            }
            
            return (d, unitType)
            
        case .imperial:
            
            let yard = distance * 1.09
            var unitType: DistanceUnitType
            var y: Double
            
            if template?.imperial == .miles {
                y = yard/1760
                unitType = .miles
            } else if template?.imperial == .yd {
                y = yard
                unitType = .yd
                
            } else {
                unitType = yard > 1760 ? .miles : .yd
                y = yard > 1760 ? yard/1760 : yard
            }
            
            return (y, unitType)
        }
        
    }
    
}


// MARK: - 时间转换
extension Unit {
    
    
    /// 时间转换
    /// - Parameters:
    ///   - seconds: 秒数
    ///   - granularity: 最大精度，目前只支持 hour，minute, second
    /// - Returns: tuple
    public func timeOf(seconds: Int, granularity: Calendar.Component) ->(hour: Int, minute: Int, second: Int) {
        
        if granularity == .second {
            return (0, 0, seconds)
        }
        
        if granularity == .minute {
            
            let minute =  seconds/60
            let second = seconds%60
            
            return (0, minute, second)
            
        }
        
        if granularity == .hour {
            
            let hour =  seconds/3600
            let minute = (seconds%3600)/60
            let second = seconds%3600 - minute * 60
            
            return (hour, minute, second)
            
        }
        
        let hour =  seconds/3600
        let minute = (seconds%3600)/60
        let second = seconds%3600 - minute * 60
        
        return (hour, minute, second)
    }
    
    
}

// MARK: - 配速计算
extension Unit {
    
    
    /// 目标配速公/英制转公制
    /// - Parameter distance: 公/英制配速
    /// - Returns: 公制
    public func goalMetricPace(_ pace: Double) ->Double {
        
        switch myType {
            
        case .metric:
            return pace
        case .imperial:
            return pace - 100
        }
    }
    
    /// 配速转换（注意： 2秒之内不进行转换）
    /// - Parameters:
    ///   - distance: 距离
    ///   - seconds: 时长
    /// - Returns: (配速， 单位固定min/distance_unit)
    public func paceOf(distance: Double, seconds: Int) ->(paceMinute: Double, unit: String) {
        
        log.debug("配速算法：\(seconds)秒钟 和 \(distance/1000)千米 = \(Double(seconds)/60.0/(distance/1000.0))")
        var d: Double = 0
        var unitType: DistanceUnitType
        switch myType {
        case .metric:
            
            d = distance/1000
            unitType = .km
            break
            
        case .imperial:
            d = distance/1760
            unitType = .miles
            break
        }
        
        let timeTuple = self.timeOf(seconds: Int(seconds), granularity: .minute)
        let minute: Double = Double(timeTuple.minute) + Double(timeTuple.second)/60.0
        
        var paceMinute: Double = 0
        if d > 0 {
            paceMinute = minute/d
        }
    
        let paceUnit = "\("unit_minute".language)/\(unitType.name)"
        
        return (paceMinute, paceUnit)
        
    }
}
